home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / mvaders / mvaders.bas < prev    next >
Encoding:
BASIC Source File  |  1997-11-04  |  28.3 KB  |  1,050 lines

  1. Option Explicit
  2.  
  3. 'Game Constants
  4. '~~~~~~~~~~~~~~
  5. 'Flags for monitoring movement keys
  6. Global Const KEY_CUR_LEFT_FLAG = 1
  7. Global Const KEY_CUR_RIGHT_FLAG = 2
  8. Global Const KEY_FIRE_FLAG = 4
  9.  
  10. 'KeyCode values for important keys
  11. Global Const KEY_CUR_LEFT = 37
  12. Global Const KEY_CUR_RIGHT = 39
  13. Global Const KEY_FIRE = 32
  14. Global Const KEY_ABORT = 65
  15. Global Const KEY_PAUSE = 80
  16. Global Const KEY_QUIT = 81
  17.  
  18. 'Game status
  19. Global Const GAME_PLAYING = 0
  20. Global Const GAME_STOPPED = 1
  21. Global Const GAME_PAUSED = 2
  22.  
  23. 'Sprite ID's
  24.  
  25. Global Const PLAYER_ID = 0
  26. Global Const BULLET_ID = 1
  27. Global Const FIRST_INVADER_ID = 2
  28. Global Const LAST_INVADER_ID = 31
  29. Global Const BONUS_SHIP_ID = 32
  30. Global Const FIRST_INVADER_BULLET_ID = 33
  31. Global Const LAST_INVADER_BULLET_ID = 35
  32. Global Const EXPLOSION_ID = 36
  33. Global Const BOSS_ID = 37
  34.  
  35. 'How many points until an extra life is granted
  36. Global Const EXTRA_LIFE = 500
  37. Global Const START_LIVES = 3
  38. Global Const MAX_LIVES = 5
  39.  
  40. 'Odd VB costants
  41. Global Const VBModal = 1        'To diaplay forms as Modal
  42.  
  43. 'Windows API rectangle structure
  44. Type RECT
  45.     iLeft As Integer
  46.     iTop As Integer
  47.     iRight As Integer
  48.     iBottom As Integer
  49. End Type
  50.  
  51. 'Windows API Point structure
  52. Type POINTAPI
  53.     iX As Integer
  54.     iY As Integer
  55. End Type
  56.  
  57. 'Constants for BitBlt() copy modes
  58. Global Const SRCCOPY = &HCC0020
  59. Global Const SRCAND = &H8800C6
  60. Global Const SRCPAINT = &HEE0086
  61. Global Const NOTSRCCOPY = &H330008
  62. Global Const SRCERASE = &H440328
  63. Global Const SRCINVERT = &H660046
  64.  
  65. 'Constants for objects Scale Mode
  66. Global Const TWIPS = 1
  67. Global Const PIXELS = 3
  68. Global Const RES_INFO = 2
  69. Global Const MINIMIZED = 1
  70.  
  71. Global Const SND_ASYNC = &H1
  72.  
  73. 'My User Defined Types
  74. '~~~~~~~~~~~~~~~~~~~~~
  75.  
  76. 'Defines an image in loaded gfx bitmap
  77. Type VBGfx
  78.     iX As Integer           'TopLeft of this gfx
  79.     iY As Integer           'TopRight of this gfx
  80.     iW As Integer           'Width
  81.     iH As Integer           'Height
  82. End Type
  83.  
  84. 'Defines a sprite on the screen
  85. Type VBSprite
  86.     iInUse As Integer       'Set if sprite is being used
  87.     iActive As Integer      '0=Sprite is off, 1=Sprite is on
  88.     iSaveOn As Integer      '0=No saves, 1=wipe as we go, 2=Bgrnd save
  89.     iGfxX As Integer        'X position of sprite in Gfx bitmap (pixel coords)
  90.     iGfxY As Integer        'Y position of sprite in Gfx bitmap (pixel coords)
  91.     iTrans As Integer       'Set if doing transparent blits
  92.     iW As Integer           'Width of the sprite
  93.     iH As Integer           'Height of the sprite
  94.     iX As Integer           'X position of sprite (pixel coords)
  95.     iY As Integer           'Y position of sprite (pixel coords)
  96.     lColour As Long         'Background colour if wiping & not restoring background
  97.     iSaveDC As Integer      'DC for background save
  98.     iSaveBmp As Integer     'BitMap for background save
  99.     iSaveSav As Integer     'BitMap from DC
  100.     iUser1 As Integer       'Varies according to sprite type
  101. End Type
  102.  
  103. 'Game preferences
  104. Type prefs
  105.     iTimer As Integer       'Timer value that controls game loop
  106.     iIGap As Integer        'Invaders separation
  107.     iISpeed As Integer      'Invaders initial speed
  108.     iIBSpeed As Integer     'Invaders bullet speed
  109.     fIBFreq As Single       'Invaders bullet frequency
  110.     iIDrop As Integer       'Invaders drop rate
  111.     iPSpeed As Integer      'Players speed
  112.     iPBSpeed As Integer     'Players bullet speed
  113. End Type
  114.  
  115. 'Game Global Variables
  116. '~~~~~~~~~~~~~~~~~~~~~
  117.  
  118. Global giKeyStatus As Integer   'Holds movement key flags
  119. Global giGameStatus As Integer  'Playing, Paused or Stopped
  120. Global giLevel As Integer       'What level player is on
  121. Global giLives As Integer       'How many lives the player has left
  122. Global giScore As Integer       'Players score
  123. Global giHiScore As Integer     'Highest Score
  124. Global gsHiName As String * 20  'Name of player with high score
  125. Global giFiring As Integer      'Set when player has fired a bullet
  126. Global giInvaders As Integer    'Number of invaders left to kill
  127. Global giFireLock As Integer    'Set to disable fire button detection
  128. Global GamePrefs As prefs       'Game preferences
  129.  
  130. 'Invaders graphics
  131. Dim miGfxDC As Integer
  132. Dim miGfxBmp As Integer
  133. Dim miGfxSav  As Integer
  134. Dim miMaskDC As Integer
  135. Dim miMaskBmp As Integer
  136. Dim miMaskSav As Integer
  137. Dim mVBGfx(22) As VBGfx         'Holds positions of all gfx images
  138. Global gVBSpr(40) As VBSprite      'Holds all sprite details
  139.  
  140. '16 Bit API functions used by MVaders
  141. Declare Function BitBlt% Lib "GDI" (ByVal hDestDC%, ByVal x%, ByVal y%, ByVal nWidth%, ByVal nHeight%, ByVal hSrcDC%, ByVal XSrc%, ByVal YSrc%, ByVal dwRop&)
  142. Declare Function SetBkColor& Lib "GDI" (ByVal hDC%, ByVal crColor&)
  143. Declare Function CreateCompatibleDC% Lib "GDI" (ByVal hDC%)
  144. Declare Function DeleteDC% Lib "GDI" (ByVal hDC%)
  145. Declare Function CreateBitmap% Lib "GDI" (ByVal nWidth%, ByVal nHeight%, ByVal nPlanes%, ByVal nBitCount%, ByVal lpBits As Any)
  146. Declare Function CreateCompatibleBitmap% Lib "GDI" (ByVal hDC%, ByVal nWidth%, ByVal nHeight%)
  147. Declare Function SelectObject% Lib "GDI" (ByVal hDC%, ByVal hObject%)
  148. Declare Function DeleteObject% Lib "GDI" (ByVal hObject%)
  149. Declare Function sndPlaySound Lib "MMSystem" (lpsound As Any, ByVal flag As Integer) As Integer
  150. Declare Function PtInRect Lib "User" (lpRect As RECT, ptRect As Any) As Integer
  151.  
  152. '32 Bit API functions
  153. 'Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
  154. 'Declare Function SetBkColor Lib "gdi32" (ByVal hdc As Long, ByVal crColor As Long) As Long
  155. 'Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
  156. 'Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
  157. 'Declare Function CreateBitmap Lib "gdi32" (ByVal nWidth As Long, ByVal nHeight As Long, ByVal nPlanes As Long, ByVal nBitCount As Long, lpBits As Any) As Long
  158. 'Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
  159. 'Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
  160. 'Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
  161. 'Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
  162.  
  163. Sub CenterForm (frm As Form)
  164.  
  165. 'Center the form on the screen
  166. frm.Move (Screen.Width - frm.Width) \ 2, (Screen.Height - frm.Height) \ 2
  167.  
  168. End Sub
  169.  
  170. Sub FreeAllSprites ()
  171.  
  172. Dim iMax As Integer
  173. Dim i As Integer
  174.  
  175. iMax = UBound(gVBSpr) - 1
  176.  
  177. For i = 0 To iMax
  178.     FreeSprite i
  179. Next i
  180.  
  181. End Sub
  182.  
  183. Sub FreeGfx ()
  184.  
  185. 'Purpose    To release all resources used to hold sprite graphics in memory.
  186. 'Entry      None, uses module level variables
  187. 'Exit       None, all resources released
  188. 'Notes      Clears all the following modal variables:
  189. '           miGfxDC, miGfxBmp, miGfxSav, miMaskDC, miMaskBmp, miMaskSav
  190.  
  191. Dim i As Integer
  192.  
  193. 'If there is a Gfx DC, free it
  194. If miGfxDC Then
  195.  
  196.     'Swap BitMap back in
  197.     i = SelectObject(miGfxDC, miGfxSav)
  198.  
  199.     'And free the DC
  200.     i = DeleteDC(miGfxDC)
  201.     miGfxDC = 0
  202.         
  203. End If
  204.  
  205. 'If there is a GfxBmp, free it
  206. If miGfxBmp Then
  207.     i = DeleteObject(miGfxBmp)
  208.     miGfxBmp = 0
  209. End If
  210.  
  211. 'Clear the swap pointer just to be complete
  212. miGfxSav = 0
  213.  
  214. 'If there is a Mask DC, free it
  215. If miMaskDC Then
  216.  
  217.     'Swap BitMap back in
  218.     i = SelectObject(miMaskDC, miMaskSav)
  219.  
  220.     'And free the DC
  221.     i = DeleteDC(miMaskDC)
  222.     miMaskDC = 0
  223.         
  224. End If
  225.  
  226. 'If there is a MaskBmp, free it
  227. If miMaskBmp Then
  228.     i = DeleteObject(miMaskBmp)
  229.     miMaskBmp = 0
  230. End If
  231.  
  232. 'Clear the swap pointer just to be complete
  233. miMaskSav = 0
  234.  
  235. End Sub
  236.  
  237. Sub FreeSprite (riId As Integer)
  238.  
  239. Dim i As Integer
  240.         
  241. 'Only proceed if sprite is used
  242. If gVBSpr(riId).iInUse Then
  243.  
  244.     'If there is a background DC, free it
  245.     If gVBSpr(riId).iSaveDC Then
  246.  
  247.         'Swap BitMap back in
  248.         i = SelectObject(gVBSpr(riId).iSaveDC, gVBSpr(riId).iSaveSav)
  249.  
  250.         'And free the DC
  251.         i = DeleteDC(gVBSpr(riId).iSaveDC)
  252.         gVBSpr(riId).iSaveDC = 0
  253.         
  254.     End If
  255.  
  256.     'If there is a background Bmp, free it
  257.     If gVBSpr(riId).iSaveBmp Then
  258.         i = DeleteObject(gVBSpr(riId).iSaveBmp)
  259.         gVBSpr(riId).iSaveBmp = 0
  260.     End If
  261.  
  262.     'Clear the swap pointer just to be complete
  263.     gVBSpr(riId).iSaveSav = 0
  264.  
  265. End If
  266.     
  267. 'Mark as no longer active or in use
  268. gVBSpr(riId).iActive = 0
  269. gVBSpr(riId).iInUse = 0
  270.  
  271. End Sub
  272.  
  273. Sub GetHiScore (riVal As Integer, rsName As String)
  274.  
  275. Dim sFName As String
  276. Dim iFNum As Integer
  277.  
  278. 'Trap error if file not accessible
  279. On Error GoTo GetHiScore_Err
  280.  
  281. 'Name of ini file
  282. sFName = App.Path & "\MVaders.dat"
  283. iFNum = FreeFile
  284.  
  285. 'Open the file
  286. Open sFName For Input As #iFNum
  287.  
  288. 'Read data from the file
  289. Input #iFNum, riVal, rsName
  290. Input #iFNum, GamePrefs.iTimer, GamePrefs.iIGap, GamePrefs.iISpeed, GamePrefs.iIBSpeed, GamePrefs.fIBFreq, GamePrefs.iIDrop, GamePrefs.iPSpeed, GamePrefs.iPBSpeed
  291.  
  292. 'Close the file
  293. Close #iFNum
  294.  
  295. Exit Sub
  296. GetHiScore_Err:
  297.  
  298. 'Default high score details
  299. riVal = 200
  300. rsName = "Mark Meany"
  301.  
  302. 'Default game preferences
  303. GamePrefs.iTimer = 50
  304. GamePrefs.iIGap = 50
  305. GamePrefs.iISpeed = 4
  306. GamePrefs.iIBSpeed = 12
  307. GamePrefs.fIBFreq = .9
  308. GamePrefs.iIDrop = 20
  309. GamePrefs.iPSpeed = 10
  310. GamePrefs.iPBSpeed = 17
  311.  
  312. Exit Sub
  313. End Sub
  314.  
  315. Function iCheckBullet (riBullet As Integer, riStart As Integer, riStop As Integer)
  316.  
  317. 'This is a very basic collision check that looks to see
  318. 'if the center of a bullet sprite is contained in the
  319. 'bounding rectangle of a range of sprites
  320.  
  321. Dim i As Integer
  322. Dim j As Integer
  323. Dim iX As Integer
  324. Dim iY As Integer
  325. Dim tRect As RECT
  326. Dim tPoint As POINTAPI
  327. Dim lPoint As Long
  328. Dim iRetVal As Integer
  329.  
  330. 'Default to no collisions
  331. iRetVal = -1
  332.  
  333. 'Define the hot spot for bullet
  334. tPoint.iX = gVBSpr(riBullet).iX + gVBSpr(riBullet).iW \ 2
  335. tPoint.iY = gVBSpr(riBullet).iY + gVBSpr(riBullet).iH \ 2
  336. lPoint = tPoint.iX + CLng(tPoint.iY) * &H10000
  337.  
  338. 'Check all sprites for collision
  339. For i = riStart To riStop
  340.     If gVBSpr(i).iActive Then
  341.         'Get bounding rectangle
  342.         tRect.iLeft = gVBSpr(i).iX
  343.         tRect.iTop = gVBSpr(i).iY
  344.         tRect.iRight = gVBSpr(i).iX + gVBSpr(i).iW
  345.         tRect.iBottom = gVBSpr(i).iY + gVBSpr(i).iH
  346.  
  347.         If PtInRect(tRect, lPoint) Then
  348.             iRetVal = i
  349.             Exit For
  350.         End If
  351.     End If
  352. Next i
  353.  
  354. iCheckBullet = iRetVal
  355.  
  356. End Function
  357.  
  358. Function iGetSprite (riId As Integer, riGfx As Integer, riTrans As Integer) As Integer
  359.  
  360. 'Purpose    To allocate a sprite from the sprite system.  Intialises resources required
  361. '           for background saves.
  362. 'Entry      riId  -- Sprite identifier
  363. '           riGfx -- Image to use for this sprite
  364. '           riTrans -- Set True if transparent blitting is to be used
  365. 'Exit
  366. 'Notes
  367.  
  368. Dim iBmp As Integer
  369. Dim iDC As Integer
  370. Dim iRetVal As Integer
  371.  
  372. 'Skip if sprite is in use
  373. If gVBSpr(riId).iInUse = False Then
  374.  
  375.     'Allocate resources for background saves
  376.     iDC = CreateCompatibleDC(miGfxDC)
  377.     If iDC Then
  378.         'Store DC
  379.         gVBSpr(riId).iSaveDC = iDC
  380.  
  381.         'Create a BitMap for the background
  382.         iBmp = CreateCompatibleBitmap(miGfxDC, mVBGfx(riGfx).iW, mVBGfx(riGfx).iH)
  383.  
  384.         'Only proceed if BitMap allocated
  385.         If iBmp Then
  386.  
  387.             'Store the BitMap
  388.             gVBSpr(riId).iSaveBmp = iBmp
  389.                 
  390.             'Swap the BitMap into the DC
  391.             gVBSpr(riId).iSaveSav = SelectObject(iDC, iBmp)
  392.  
  393.             'Copy details of initial gfx
  394.             gVBSpr(riId).iInUse = True
  395.             gVBSpr(riId).iGfxX = mVBGfx(riGfx).iX
  396.             gVBSpr(riId).iGfxY = mVBGfx(riGfx).iY
  397.             gVBSpr(riId).iW = mVBGfx(riGfx).iW
  398.             gVBSpr(riId).iH = mVBGfx(riGfx).iH
  399.             gVBSpr(riId).iTrans = riTrans
  400.  
  401.             'Indicate success
  402.             iRetVal = True
  403.  
  404.         End If
  405.  
  406.     End If
  407.  
  408.     'Free resources if allocation failed
  409.     If iRetVal = False Then FreeSprite riId
  410.  
  411. End If
  412.  
  413. 'Return success of the operation
  414. iGetSprite = iRetVal
  415.  
  416. End Function
  417.  
  418. Sub InitGame ()
  419.  
  420. 'Init global vars for the game
  421. giScore = 0
  422. giLives = START_LIVES
  423. giLevel = 1
  424. GetHiScore giHiScore, gsHiName
  425.  
  426. 'Load and initialise the graphics used in the game
  427. LoadGfx frmMain.picLoader
  428.  
  429. End Sub
  430.  
  431. Sub InitL1 (riDown As Integer)
  432.  
  433. 'Purpose    To set up sprites etc for level 1 of game
  434.  
  435. Dim i As Integer
  436. Dim j As Integer
  437. Dim k As Integer
  438. Dim iX As Integer
  439. Dim iY As Integer
  440. Dim iDC As Integer
  441.  
  442. 'Make sure game is stopped
  443. 'giGameStatus = GAME_STOPPED
  444.  
  445. 'Free sprites in use
  446. FreeAllSprites
  447.  
  448. 'Get DC to work with
  449. iDC = frmMain.picGame.hDC
  450.  
  451. 'Build the players ship
  452. i = iGetSprite(PLAYER_ID, 10, 0)
  453. If i Then
  454.     iX = (frmMain.picGame.Width \ Screen.TwipsPerPixelX) \ 2
  455.     iY = frmMain.picGame.Height \ Screen.TwipsPerPixelY - 27
  456.     VBSprActivateSprite iDC, 0, iX, iY
  457. End If
  458.  
  459. 'Build players bullet, leave inactive, this uses transparent blitting!
  460. i = iGetSprite(BULLET_ID, 12, 1)
  461.  
  462. 'Build the invader sprites
  463. giInvaders = 0
  464. For j = FIRST_INVADER_ID To LAST_INVADER_ID
  465.     k = j - FIRST_INVADER_ID
  466.     i = iGetSprite(j, 2 * (k \ 6), 0)
  467.     If i Then
  468.         iX = (k Mod 6) * GamePrefs.iIGap + 10
  469.         iY = (k \ 6) * 30 + 16 + riDown
  470.         gVBSpr(j).iUser1 = 1
  471.         VBSprActivateSprite iDC, j, iX, iY
  472.         giInvaders = giInvaders + 1
  473.     End If
  474. Next j
  475.  
  476. 'Build the invaders bullet sprites
  477. For j = FIRST_INVADER_BULLET_ID To LAST_INVADER_BULLET_ID
  478.     i = iGetSprite(j, 17, 0)
  479. Next j
  480.  
  481. 'Build the explosion sprite
  482. i = iGetSprite(EXPLOSION_ID, 14, 0)
  483.  
  484. 'Build the bonus ships sprite
  485. i = iGetSprite(BONUS_SHIP_ID, 18, 0)
  486.  
  487. 'Build the Boss
  488. i = iGetSprite(BOSS_ID, 20, 0)
  489.  
  490. 'Configure game variables
  491. giFiring = False
  492.  
  493. End Sub
  494.  
  495. Sub InitL2 (ByVal viInc As Integer)
  496.  
  497. 'Purpose    To set up sprites etc for level 1 of game
  498.  
  499. Dim i As Integer
  500. Dim j As Integer
  501. Dim k As Integer
  502. Dim iX As Integer
  503. Dim iY As Integer
  504. Dim iDC As Integer
  505.  
  506. 'Make sure game is stopped
  507. 'giGameStatus = GAME_STOPPED
  508.  
  509. 'Free sprites in use
  510. FreeAllSprites
  511.  
  512. 'Get DC to work with
  513. iDC = frmMain.picGame.hDC
  514.  
  515. 'Build the players ship
  516. i = iGetSprite(PLAYER_ID, 10, 0)
  517. If i Then
  518.     iX = (frmMain.picGame.Width \ Screen.TwipsPerPixelX) \ 2
  519.     iY = frmMain.picGame.Height \ Screen.TwipsPerPixelY - 27
  520.     VBSprActivateSprite iDC, 0, iX, iY
  521. End If
  522.  
  523. 'Build players bullet, leave inactive, this uses transparent blitting!
  524. i = iGetSprite(BULLET_ID, 12, 1)
  525.  
  526. giInvaders = 0
  527. For i = 0 To 2
  528.     For j = 0 To 2
  529.         k = iGetSprite(FIRST_INVADER_ID + giInvaders, 20, 0)
  530.         If k Then
  531.             iX = j * gVBSpr(FIRST_INVADER_ID + giInvaders).iW + GamePrefs.iIGap + 10
  532.             iY = i * gVBSpr(FIRST_INVADER_ID + giInvaders).iH + 5
  533.             gVBSpr(FIRST_INVADER_ID + giInvaders).iUser1 = 4 + viInc
  534.             VBSprActivateSprite iDC, FIRST_INVADER_ID + giInvaders, iX, iY
  535.             giInvaders = giInvaders + 1
  536.         End If
  537.     Next j
  538. Next i
  539.             
  540. 'Build the invaders bullet sprites
  541. For j = FIRST_INVADER_BULLET_ID To LAST_INVADER_BULLET_ID
  542.     i = iGetSprite(j, 17, 0)
  543. Next j
  544.  
  545. 'Build the explosion sprite
  546. i = iGetSprite(EXPLOSION_ID, 14, 0)
  547.  
  548. 'Build the bonus ships sprite
  549. i = iGetSprite(BONUS_SHIP_ID, 18, 0)
  550.  
  551. 'Build the Boss
  552. i = iGetSprite(BOSS_ID, 20, 0)
  553.  
  554. 'Configure game variables
  555. giFiring = False
  556.  
  557. End Sub
  558.  
  559. Function iVBSprCollision (riId1 As Integer, riId2 As Integer) As Integer
  560.  
  561. Dim x1 As Integer
  562. Dim y1 As Integer
  563. Dim x2 As Integer
  564. Dim y2 As Integer
  565. Dim xx1 As Integer
  566. Dim yy1 As Integer
  567. Dim xx2 As Integer
  568. Dim yy2 As Integer
  569. Dim iRetVal As Integer
  570.  
  571. x1 = gVBSpr(riId1).iX
  572. y1 = gVBSpr(riId1).iY
  573. x2 = x1 + gVBSpr(riId1).iW - 1
  574. y2 = y1 + gVBSpr(riId1).iH - 1
  575.  
  576. xx1 = gVBSpr(riId2).iX
  577. yy1 = gVBSpr(riId2).iY
  578. xx2 = xx1 + gVBSpr(riId2).iW - 1
  579. yy2 = yy1 + gVBSpr(riId2).iH - 1
  580.  
  581. 'Default to a collision
  582. iRetVal = True
  583.  
  584. 'Check if collision is impossible
  585. If (xx2 < x1) Then iRetVal = False
  586. If (yy2 < y1) Then iRetVal = False
  587. If (xx1 > x2) Then iRetVal = False
  588. If (yy1 > y2) Then iRetVal = False
  589.  
  590. iVBSprCollision = iRetVal
  591.  
  592. End Function
  593.  
  594. Sub LoadGfx (picGfx As PictureBox)
  595.  
  596. 'Purpose    To load a bitmap that contains all sprite gfx for game into a DC.
  597. '           Also creates mask for all sprites ready for transparent BitBlt().
  598. 'Entry      picGfx - A PictureBox to use LoadPicture with.  Note that this is
  599. '           also used to obtain a compatible DC for loaded file.
  600. '           Autosize=True, AutoRedraw=True,Visible=False,ScaleMode=PIXELS
  601. 'Notes      Uses module level variables to store resource pointers:
  602. '           miGfxDC, miGfxBmp, miGfxSav, miMaskDC, miMaskBmp, miMaskSav
  603.  
  604. Dim iSuccess As Integer
  605. Dim iDC As Integer
  606. Dim iBmp As Integer
  607. Dim iTBmp As Integer
  608. Dim iW As Integer
  609. Dim iH As Integer
  610. Dim iScaleMode As Integer
  611. Dim i As Integer
  612. Dim lColour As Long
  613. Dim sFName As String
  614.  
  615. 'Fix name of data file
  616. sFName = App.Path & "\mvaders.bmp"
  617.  
  618. 'Default to failure
  619. iSuccess = False
  620.  
  621. 'Load the gfx file into the picturebox
  622. picGfx.Picture = LoadPicture(sFName)
  623.  
  624. 'Make scale mode for PictureBox pixels as required by GDI
  625. iScaleMode = picGfx.ScaleMode
  626. picGfx.ScaleMode = PIXELS
  627.  
  628. 'Get dimensions of this graphic
  629. iW = picGfx.ScaleWidth
  630. iH = picGfx.ScaleHeight
  631.  
  632. 'Create a DC for the sprite
  633. iDC = CreateCompatibleDC(picGfx.hDC)
  634.  
  635. 'Only proceed if DC allocated
  636. If iDC Then
  637.             
  638.     'Store DC
  639.     miGfxDC = iDC
  640.  
  641.     'Create a BitMap for this sprite
  642.     iBmp = CreateCompatibleBitmap(picGfx.hDC, iW, iH)
  643.  
  644.     'Only proceed if BitMap allocated
  645.     If iBmp Then
  646.  
  647.         'Store the BitMap
  648.         miGfxBmp = iBmp
  649.                 
  650.         'Swap the BitMap into the DC
  651.         miGfxSav = SelectObject(iDC, iBmp)
  652.  
  653.         'Copy graphics into the DC
  654.         i = BitBlt(iDC, 0, 0, iW, iH, picGfx.hDC, 0, 0, SRCCOPY)
  655.  
  656.         'Create a DC for the mask
  657.         iDC = CreateCompatibleDC(picGfx.hDC)
  658.  
  659.         'Only proceed if DC allocated
  660.         If iDC Then
  661.             
  662.             'Store DC
  663.             miMaskDC = iDC
  664.  
  665.             'Create a BitMap for this mask
  666.             iBmp = CreateBitmap(iW, iH, 1, 1, ByVal 0&)
  667.  
  668.             'Only proceed if BitMap allocated
  669.             If iBmp Then
  670.  
  671.                 'Store the BitMap
  672.                 miMaskBmp = iBmp
  673.                 
  674.                 'Swap the BitMap into the DC
  675.                 miMaskSav = SelectObject(iDC, iBmp)
  676.  
  677.                 'Generate the mask, uses QBColor(0) as transparent
  678.                 lColour = SetBkColor(picGfx.hDC, QBColor(0))
  679.                 i = BitBlt(iDC, 0, 0, iW, iH, picGfx.hDC, 0, 0, SRCCOPY)
  680.                 lColour = SetBkColor(picGfx.hDC, lColour)
  681.  
  682.                 'Flag success
  683.                 iSuccess = True
  684.  
  685.                 'Define images in this bitmap
  686.                 
  687.                 mVBGfx(0).iX = 0        'Alien 1, Frame 1
  688.                 mVBGfx(0).iY = 0
  689.                 mVBGfx(0).iW = 32
  690.                 mVBGfx(0).iH = 20
  691.                 
  692.                 mVBGfx(1).iX = 34       'Alien 1, Frame 2
  693.                 mVBGfx(1).iY = 0
  694.                 mVBGfx(1).iW = 32
  695.                 mVBGfx(1).iH = 20
  696.  
  697.                 mVBGfx(2).iX = 0        'Alien 2, Frame 1
  698.                 mVBGfx(2).iY = 23
  699.                 mVBGfx(2).iW = 32
  700.                 mVBGfx(2).iH = 20
  701.                 
  702.                 mVBGfx(3).iX = 34       'Alien 2, Frame 2
  703.                 mVBGfx(3).iY = 23
  704.                 mVBGfx(3).iW = 32
  705.                 mVBGfx(3).iH = 20
  706.                 
  707.                 mVBGfx(4).iX = 0        'Alien 3, Frame 1
  708.                 mVBGfx(4).iY = 45
  709.                 mVBGfx(4).iW = 32
  710.                 mVBGfx(4).iH = 20
  711.                 
  712.                 mVBGfx(5).iX = 34       'Alien 3, Frame 2
  713.                 mVBGfx(5).iY = 45
  714.                 mVBGfx(5).iW = 32
  715.                 mVBGfx(5).iH = 20
  716.                 
  717.                 mVBGfx(6).iX = 0        'Alien 4, Frame 1
  718.                 mVBGfx(6).iY = 69
  719.                 mVBGfx(6).iW = 32
  720.                 mVBGfx(6).iH = 18
  721.                 
  722.                 mVBGfx(7).iX = 34       'Alien 4, Frame 2
  723.                 mVBGfx(7).iY = 69
  724.                 mVBGfx(7).iW = 32
  725.                 mVBGfx(7).iH = 18
  726.                 
  727.                 mVBGfx(8).iX = 0        'Alien 5, Frame 1
  728.                 mVBGfx(8).iY = 89
  729.                 mVBGfx(8).iW = 32
  730.                 mVBGfx(8).iH = 20
  731.                 
  732.                 mVBGfx(9).iX = 34       'Alien 5, Frame 2
  733.                 mVBGfx(9).iY = 89
  734.                 mVBGfx(9).iW = 32
  735.                 mVBGfx(9).iH = 20
  736.  
  737.                 mVBGfx(10).iX = 0       'Players ship Frame 1
  738.                 mVBGfx(10).iY = 113
  739.                 mVBGfx(10).iW = 32
  740.                 mVBGfx(10).iH = 17
  741.                 
  742.                 mVBGfx(11).iX = 34      'Players ship Frame 2
  743.                 mVBGfx(11).iY = 113
  744.                 mVBGfx(11).iW = 32
  745.                 mVBGfx(11).iH = 17
  746.                 
  747.                 mVBGfx(12).iX = 1       'Players bullet frame 1
  748.                 mVBGfx(12).iY = 135
  749.                 mVBGfx(12).iW = 10
  750.                 mVBGfx(12).iH = 18
  751.  
  752.                 mVBGfx(13).iX = 14      'Players bullet frame 2
  753.                 mVBGfx(13).iY = 135
  754.                 mVBGfx(13).iW = 10
  755.                 mVBGfx(13).iH = 18
  756.  
  757.                 mVBGfx(14).iX = 39      'Explosion frame 1
  758.                 mVBGfx(14).iY = 136
  759.                 mVBGfx(14).iW = 24
  760.                 mVBGfx(14).iH = 17
  761.  
  762.                 mVBGfx(15).iX = 3       'Explosion frame 2
  763.                 mVBGfx(15).iY = 157
  764.                 mVBGfx(15).iW = 24
  765.                 mVBGfx(15).iH = 17
  766.  
  767.                 mVBGfx(16).iX = 30      'Explosion frame 3
  768.                 mVBGfx(16).iY = 157
  769.                 mVBGfx(16).iW = 24
  770.                 mVBGfx(16).iH = 17
  771.  
  772.                 mVBGfx(17).iX = 27      'Invaders bullet
  773.                 mVBGfx(17).iY = 136
  774.                 mVBGfx(17).iW = 10
  775.                 mVBGfx(17).iH = 16
  776.  
  777.                 mVBGfx(18).iX = 2       'Bonus ship frame 1
  778.                 mVBGfx(18).iY = 177
  779.                 mVBGfx(18).iW = 24
  780.                 mVBGfx(18).iH = 14
  781.  
  782.                 mVBGfx(19).iX = 38      'Bonus ship frame 2
  783.                 mVBGfx(19).iY = 177
  784.                 mVBGfx(19).iW = 24
  785.                 mVBGfx(19).iH = 14
  786.  
  787.                 mVBGfx(20).iX = 76      'Boss frame 1
  788.                 mVBGfx(20).iY = 0
  789.                 mVBGfx(20).iW = 132
  790.                 mVBGfx(20).iH = 85
  791.  
  792.                 mVBGfx(21).iX = 76      'Boss frame 2
  793.                 mVBGfx(21).iY = 90
  794.                 mVBGfx(21).iW = 132
  795.                 mVBGfx(21).iH = 85
  796.  
  797.             End If
  798.         End If
  799.     End If
  800. End If
  801.     
  802. 'If we failed to load the file, free resources
  803. If iSuccess = False Then FreeGfx
  804.  
  805. 'Reset Scale Mode of Picture Box
  806. picGfx.ScaleMode = iScaleMode
  807. picGfx.Picture = LoadPicture()
  808.  
  809. End Sub
  810.  
  811. Sub Main ()
  812.  
  813. 'Initialise variables
  814. giKeyStatus = 0
  815. giGameStatus = GAME_STOPPED
  816.  
  817. 'Load the game window
  818. Load frmMain
  819.  
  820. 'Initialise the game
  821. InitGame
  822.  
  823. 'Show form as modal
  824. frmMain.Show VBModal
  825.  
  826. 'Make sure form is unloaded
  827. Unload frmMain
  828.  
  829. 'Free gfx resources
  830. FreeGfx
  831.  
  832. 'Free sprite resources
  833. FreeAllSprites
  834.  
  835. 'Save high score info
  836. SaveHiScore giHiScore, gsHiName
  837.  
  838. End Sub
  839.  
  840. Sub PlayHitMe ()
  841.  
  842. Dim i As Integer
  843. Dim sFName As String
  844.  
  845. i = Int(Rnd * 10) + 1
  846. sFName = App.Path & "\dead" & Format$(i, "") & ".wav"
  847. i = sndPlaySound(ByVal CStr(sFName), SND_ASYNC)
  848.  
  849. End Sub
  850.  
  851. Sub SaveHiScore (riVal As Integer, rsName As String)
  852. Dim sFName As String
  853. Dim iFNum As Integer
  854.  
  855. 'Trap error if file not accessible
  856. On Error GoTo SaveHiScore_Err
  857.  
  858. 'Name of ini file
  859. sFName = App.Path & "\MVaders.dat"
  860. iFNum = FreeFile
  861.  
  862. 'Open the file
  863. Open sFName For Output As #iFNum
  864.  
  865. 'Read data from the file
  866. Write #iFNum, riVal, rsName
  867. Write #iFNum, GamePrefs.iTimer, GamePrefs.iIGap, GamePrefs.iISpeed, GamePrefs.iIBSpeed, GamePrefs.fIBFreq, GamePrefs.iIDrop, GamePrefs.iPSpeed, GamePrefs.iPBSpeed
  868.  
  869. 'Close the file
  870. Close #iFNum
  871.  
  872. Exit Sub
  873. SaveHiScore_Err:
  874.  
  875. riVal = 1000
  876. rsName = "Mark Meany"
  877. Exit Sub
  878. End Sub
  879.  
  880. Sub ShowGameOver ()
  881.  
  882. Dim i As Integer
  883. Dim iX As Integer
  884. Dim iY As Integer
  885.  
  886. iX = ((frmMain.picGame.Width \ Screen.TwipsPerPixelX) - 89) \ 2
  887. iY = ((frmMain.picGame.Height \ Screen.TwipsPerPixelY) - 57) \ 2
  888.  
  889. i = BitBlt(frmMain.picGame.hDC, iX, iY, 89, 57, miGfxDC, 0, 205, SRCCOPY)
  890.  
  891. End Sub
  892.  
  893. Sub SplatGfx (iSX As Integer, iSY As Integer, iW As Integer, iH As Integer, picDst As PictureBox, iDX As Integer, iDY As Integer)
  894.  
  895. 'Purpose    Copies gfx data to display for debug
  896.  
  897. Dim i As Integer
  898.  
  899. i = BitBlt(picDst.hDC, iSX, iSY, iW, iH, miGfxDC, iDX, iDY, SRCCOPY)
  900.  
  901. End Sub
  902.  
  903. Sub VBSprActivateSprite (hDC As Integer, riId As Integer, riX As Integer, riY As Integer)
  904.  
  905. 'Purpose    Turn a sprite on so that it will be displayed
  906. 'Entry      riId - The sprite to activate
  907. '           riX, riY - where to position the sprite
  908. 'Notes      Sprite must be in use and inactive
  909.  
  910. Dim i As Integer
  911.  
  912. If riId < UBound(gVBSpr) Then
  913.     If gVBSpr(riId).iInUse Then
  914.         If gVBSpr(riId).iActive = False Then
  915.             gVBSpr(riId).iActive = True
  916.             gVBSpr(riId).iX = riX
  917.             gVBSpr(riId).iY = riY
  918.         End If
  919.     End If
  920. End If
  921.  
  922. End Sub
  923.  
  924. Sub VBSprAnimateSprite (riId As Integer, riGfx As Integer)
  925.  
  926. 'Purpose    Change anim frame of a sprite
  927.  
  928. 'Notes      Only call if sprite has had background restored
  929.  
  930. 'Do relative move
  931. gVBSpr(riId).iGfxX = mVBGfx(riGfx).iX
  932. gVBSpr(riId).iGfxY = mVBGfx(riGfx).iY
  933.  
  934. End Sub
  935.  
  936. Sub VBSprDeactivateSprite (riId As Integer)
  937.  
  938. If riId < UBound(gVBSpr) Then
  939.     If gVBSpr(riId).iInUse Then gVBSpr(riId).iActive = False
  940. End If
  941.  
  942. End Sub
  943.  
  944. Sub VBSprDrawSprites (hDC As Integer)
  945.  
  946. 'Purpose    To save background & draw sprites with transparent bgrnd
  947.  
  948. Dim i As Integer
  949. Dim iMax As Integer
  950. Dim j As Integer
  951.  
  952. 'Get number of sprites
  953. iMax = UBound(gVBSpr) - 1
  954.  
  955. 'Check each sprite
  956. For i = 0 To iMax
  957.  
  958.     'Sprite must be active
  959.     If gVBSpr(i).iActive Then
  960.  
  961.         'If transparent, do funky thing
  962.         If gVBSpr(i).iTrans Then
  963.  
  964.             'Copy the mask to screen
  965.             j = BitBlt(hDC, gVBSpr(i).iX, gVBSpr(i).iY, gVBSpr(i).iW, gVBSpr(i).iH, miMaskDC, gVBSpr(i).iGfxX, gVBSpr(i).iGfxY, SRCAND)
  966.  
  967.             'Copy the sprite to screen
  968.             j = BitBlt(hDC, gVBSpr(i).iX, gVBSpr(i).iY, gVBSpr(i).iW, gVBSpr(i).iH, miGfxDC, gVBSpr(i).iGfxX, gVBSpr(i).iGfxY, SRCINVERT)
  969.  
  970.         'Otherwise do a straight forward copy
  971.         Else
  972.  
  973.             j = BitBlt(hDC, gVBSpr(i).iX, gVBSpr(i).iY, gVBSpr(i).iW, gVBSpr(i).iH, miGfxDC, gVBSpr(i).iGfxX, gVBSpr(i).iGfxY, SRCCOPY)
  974.  
  975.         End If
  976.     End If
  977. Next i
  978.  
  979. End Sub
  980.  
  981. Sub VBSprExtent (riXMin As Integer, riXMax As Integer, riYMax As Integer, ByVal viStart As Integer, ByVal viStop As Integer)
  982.  
  983. 'Purpose    To determine extremes of a sprite pack (invaders)
  984. 'Entry      riXMin -- container for smallest X value
  985. '           riXMax -- container for largest X value
  986. '           riStart -- Sprite Id to start search from
  987. '           riStop -- Sprite Id to stop search at
  988.  
  989. Dim i As Integer
  990. Dim x As Integer
  991.  
  992. riXMin = gVBSpr(viStart).iX
  993. riXMax = riXMin
  994. riYMax = -1
  995.  
  996. For i = viStart + 1 To viStop
  997.     If gVBSpr(i).iActive Then
  998.         x = gVBSpr(i).iX
  999.         If x < riXMin Then riXMin = x
  1000.         If x > riXMax Then riXMax = x
  1001.         If gVBSpr(i).iY > riYMax Then riYMax = gVBSpr(i).iY
  1002.     End If
  1003. Next i
  1004.  
  1005. End Sub
  1006.  
  1007. Sub VBSprMoveSpriteRel (riId As Integer, riX As Integer, riY As Integer, riGfx As Integer)
  1008.  
  1009. 'Purpose    Move a sprite relative to its current position
  1010.  
  1011. 'Notes      Only call if sprite has had background restored
  1012.  
  1013. 'Spriute must be active to move it
  1014. If gVBSpr(riId).iActive Then
  1015.  
  1016.     'Do relative move
  1017.     gVBSpr(riId).iX = gVBSpr(riId).iX + riX
  1018.     gVBSpr(riId).iY = gVBSpr(riId).iY + riY
  1019.     gVBSpr(riId).iGfxX = mVBGfx(riGfx).iX
  1020.     gVBSpr(riId).iGfxY = mVBGfx(riGfx).iY
  1021.  
  1022. End If
  1023.  
  1024. End Sub
  1025.  
  1026. Sub VBSprRestoreBgrnd (hDC As Integer)
  1027.  
  1028. 'Purpose    Restores all saved backgrounds
  1029.  
  1030. Dim i As Integer
  1031. Dim iMax As Integer
  1032. Dim j As Integer
  1033.  
  1034. iMax = UBound(gVBSpr) - 1
  1035.  
  1036. 'Go backwards through the array to restore in reverse order to save
  1037. For i = iMax To 0 Step -1
  1038.  
  1039.     'Sprite must be on
  1040.     If gVBSpr(i).iActive Then
  1041.  
  1042.         'Clear background
  1043.         j = BitBlt(hDC, gVBSpr(i).iX, gVBSpr(i).iY, gVBSpr(i).iW, gVBSpr(i).iH, hDC, gVBSpr(i).iX, gVBSpr(i).iY, SRCERASE)
  1044.  
  1045.     End If
  1046. Next i
  1047.  
  1048. End Sub
  1049.  
  1050.